//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using Eas.WebCrawler.Interfaces;

namespace Eas.WebCrawler.Model.Gateway
{
    /// <summary>This interface abstracts away all System.Net usage from the Eas.WebCrawler application.</summary>
    /// <remarks>This class was designed to enable the mock object pattern in my unit testing.  If you look at <see cref="System.Net"/> you will see that this class is a very thin wrapper over it.</remarks>
    /// <seealso cref="System.Net.WebRequest"/>
    /// <seealso cref="System.Net.WebResponse"/>
    public interface WebGateway 
    {
        /// <summary>Creates a new <see cref="WebRequestInterface"/> for the passed-in request.</summary>
        /// <param name="processingState">A <see cref="ProcessingState"/> whose <code>Request</code> property contains data about what uri to use for the created request pbject.</param>
        /// <returns>A new <see cref="WebRequestInterface"/> wrapping a <see cref="System.Net.WebRequest"/> object.</returns>
        WebRequestInterface CreateWebRequest(ProcessingState processingState);
        
        /// <summary>Calls into BeginGetResponse on the <see cref="WebRequestInterface"/> contained in the passed in <paramref name="processingState"/>.</summary>
        /// <param name="processingState">A <see cref="ProcessingState"/> whose <see cref="ProcessingState.WebRequest"/> property has been filled in.</param>
        /// <param name="callback">The callback function to call, if any, when GetResponse completes.</param>
        /// <param name="state">State passed into the callback for asynchronous processing.</param>
        /// <returns>An <see cref="IAsyncResult"/>.</returns>
        IAsyncResult BeginGetResponse(ProcessingState processingState, AsyncCallback callback, object state);

        /// <summary>Returns a <see cref="WebResponseInterface"/>created by the completion of a GetResponse action.</summary>
        /// <param name="processingState">A <see cref="ProcessingState"/> whose <see cref="ProcessingState.WebRequest"/> property has been filled in.</param>
        /// <param name="result">A <see cref="WebResponseInterface"/> wrapping a <see cref="System.Net.WebResponse"/> object.</param>
        /// <returns></returns>
        WebResponseInterface EndGetResponse(ProcessingState processingState, IAsyncResult result);

        /// <summary>Looks at the <see cref="WebResponseInterface"/> in the passed-in <paramref name="processingState"/> and detects if the response is a redirect.</summary>
        /// <param name="processingState">A <see cref="ProcessingState"/> whose <see cref="ProcessingState.WebResponse"/> property has been filled in.</param>
        /// <returns><code>true</code> if the returned response is a redirect, otherwise <code>false</code>.</returns>
        bool IsRedirect(ProcessingState processingState);

        /// <summary>Retrieves the redirect Uri from a web response representing a redirect</summary>
        /// <param name="processingState">A <see cref="ProcessingState"/> whose <see cref="ProcessingState.WebResponse"/> property has been filled in.</param>
        /// <returns>The <see cref="System.Uri"/> which is the target of the redirect.</returns>
        Uri GetRedirectUri(ProcessingState processingState);

        /// <summary>Retrieves the response stream from a <see cref="WebResponseInterface"/>.</summary>
        /// <param name="processingState">A <see cref="ProcessingState"/> whose <see cref="ProcessingState.WebResponse"/> property has been filled in.</param>
        /// <returns>A new <see cref="System.IO.Stream"/> which contains the body of the response.</returns>
        System.IO.Stream GetResponseStream(ProcessingState processingState);

        /// <summary>Gets the http response code for a failed web request.</summary>
        /// <param name="exception">The <see cref="System.Exception"/> thrown when the request failed.</param>
        /// <returns>A number representing the http response code for the failure.</returns>
        /// <example>If the request failed because the requested Uri could not be found, this function will return <code>404</code>.</example>
        int GetResponseCode(System.Net.WebException exception);

        /// <summary>An asynchronous function which reads data from a stream that was returned from a <see cref="WebResponseInterface"/> (though to be honest, it would perform the read on any stream).</summary>
        /// <param name="processingState">A <see cref="ProcessingState"/> whose <see cref="ProcessingState.ResponseStream"/> property has been filled in.</param>
        /// <param name="buffer">The byte array into which the stream will write out it's contents.</param>
        /// <param name="offset">The offset into the <paramref name="buffer"/> at which to write out the stream's contents.</param>
        /// <param name="count">The maximum number of bytes that can be written into the <paramref name="buffer"/></param>
        /// <param name="callback">The callback function to call, if any, when GetResponse completes.</param>
        /// <param name="state">State passed into the callback for asynchronous processing.</param>
        /// <returns>The asynchronous result token for the request.</returns>
        IAsyncResult BeginReadStream(ProcessingState processingState, byte[] buffer, int offset, int count, AsyncCallback callback, object state);
        
        /// <summary>The completing function of <see cref="BeginReadStream"/>.</summary>
        /// <param name="processingState">A <see cref="ProcessingState"/> whose <see cref="ProcessingState.ResponseStream"/> property has been filled in.</param>
        /// <param name="result">The <see cref="IAsyncResult"/> returned from the begin method.</param>
        /// <returns>The number of bytes read.</returns>
        int EndReadStream(ProcessingState processingState, IAsyncResult result);

        /// <summary>Determines if the contents of the web response is text (like html) or binary (like images and movies).</summary>
        /// <param name="processingState">A <see cref="ProcessingState"/> whose <see cref="ProcessingState.WebResponse"/> property has been filled in.</param>
        /// <returns><code>true</code> if the uri points to text, otherwise <code>false</code>.</returns>
        bool ResponseIsText(ProcessingState processingState);

        /// <summary>Tells System.Net how many active connections to one end point can be open at the same time.</summary>
        /// <param name="limit">The number of active connections to one end point can be open at the same time.</param>
        void SetConnectionLimit(int limit);
    }
}
